home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / icemalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-08  |  29.4 KB  |  1,194 lines  |  [TEXT/ALFA]

  1. /*
  2. **
  3. ** Notice.
  4. **
  5. ** This source code was written by Tim Endres. time@ice.com
  6. ** Copyright 1988-1991 © By Tim Endres. All rights reserved.
  7. ** 8840 Main Street, Whitmore Lake, MI  48189
  8. **
  9. ** You may use this source code for any purpose you can dream
  10. ** of as long as this notice is never modified nor removed.
  11. **
  12. ** Please email me any improvements that you might make. Any
  13. ** reasonable form of diff (compare) on the files changes will
  14. ** do nicely. You can mail "time@ice.com". Thank you.
  15. **
  16. ** BTW: In case it is not obvious, do not #define DOCUMENTATION ;)
  17. **
  18. */
  19.  
  20.  
  21. #include "icemalloc.h"
  22. _mem_pool_ptr                _mem_pool_forest = & _mem_system_pool;
  23.  
  24. #define mNEWPTR(size)            ( NewPtrClear ( (size) ) )
  25. #define mDISPOSPTR(ptr)            ( DisposPtr ( (ptr) ) )
  26.  
  27. #define DEBUG
  28.  
  29. #ifdef DOCUMENTATION
  30.  
  31.     malloc() will allocate "size" bytes from the default malloc pool.
  32.     
  33. #endif
  34.  
  35. char    *
  36. icemalloc ( size )
  37. u_long    size;
  38. {
  39. _mem_pool_ptr    pool;
  40.  
  41.     pool = _default_mem_pool;
  42.     if (pool == (_mem_pool_ptr)0)
  43.         return (char *)0;
  44.     
  45.     return _pool_malloc(pool, size);
  46.     }
  47.  
  48.  
  49. #ifdef DOCUMENTATION
  50.  
  51.     free() will free the memory occupied by the "ptr" allocated by malloc().
  52.     
  53. #endif
  54.  
  55. icefree ( ptr )
  56. char    *ptr;
  57. {
  58.     return _pool_free(ptr);
  59.     }
  60.  
  61.  
  62. #ifdef DOCUMENTATION
  63.  
  64.     set_default_pool() - given a pool id, this routine will make it the default
  65.     pool from which malloc() allocates memory.
  66.     
  67. #endif
  68.  
  69. set_default_pool ( id )
  70. int        id;
  71. {
  72. _mem_pool_ptr    pool, last;
  73.  
  74.     if (_default_mem_pool->id == id)
  75.         return 0;
  76.     
  77.     last = _default_mem_pool;
  78.     pool = _default_mem_pool->next;
  79.     for ( ; pool != (_mem_pool_ptr)0 ; pool = pool->next) {
  80.         if (pool->id == id) {
  81.             last->next = pool->next;
  82.             pool->next = _default_mem_pool;
  83.             _default_mem_pool = pool;
  84.             return 0;
  85.             }
  86.         }
  87.     
  88.     return -1;
  89.     }
  90.  
  91.  
  92. #ifdef DOCUMENTATION
  93.  
  94.     new_malloc_pool() creates a new pool from which memory can be malloc()-ed.
  95.     
  96. #endif
  97.  
  98. _mem_pool_ptr
  99. new_malloc_pool ( id, pref_blk_size )
  100. int        id;
  101. u_long    pref_blk_size;
  102. {
  103. _mem_pool_ptr    new_pool;
  104.  
  105.     new_pool = find_pool(id);
  106.     if (new_pool != NULL)            /* ? Is this the best choice? Its not ID-able */
  107.         return new_pool;
  108.  
  109.     new_pool = (_mem_pool_ptr) mNEWPTR( sizeof(_mem_pool) );
  110.     if (new_pool == (_mem_pool_ptr)0)
  111.         return new_pool;
  112.     
  113.     new_pool->id = id;                            /* The pool's ID. */
  114.     new_pool->pref_blk_size = pref_blk_size;    /* The preferred size of new blks. */
  115.     new_pool->blk_list = NULL;                    /* The list of blocks in the pool. */
  116.     
  117.     /* The next two lines insert right after the default, so we don't change it. */
  118.     new_pool->next = _mem_pool_forest->next;
  119.     _mem_pool_forest->next = new_pool;
  120.  
  121. #ifdef _PM_STATS
  122.     new_pool->total_memory = 0;            /* The total allocated memory by this pool */
  123.     new_pool->total_storage = 0;        /* The total malloc-able storage in this pool */
  124.     new_pool->total_malloc = 0;            /* The total malloc-ed storage not freed. */
  125.     new_pool->max_blk_size = 0;            /* The maximum block size allocated. */
  126.     new_pool->ave_req_size = 0.0;        /* The ave allocated request size */
  127.     new_pool->ave_req_total = 0;        /* The total requests in the average. */
  128.     new_pool->ave_blk_size = 0.0;        /* The ave sallocated blk size */
  129.     new_pool->ave_blk_total = 0;        /* The total blks in the average. */
  130. #endif
  131.  
  132.     return new_pool;
  133.     }
  134.  
  135.  
  136. #ifdef DOCUMENTATION
  137.  
  138.     find_pool() will find the pool with the given "id" and return its pointer.
  139.     
  140. #endif
  141.  
  142. _mem_pool_ptr
  143. find_pool ( id )
  144. int        id;
  145. {
  146. _mem_pool_ptr    pool;
  147.  
  148.     for (pool = _mem_pool_forest ; pool != (_mem_pool_ptr)0 ; pool = pool->next) {
  149.         if (pool->id == id)
  150.             break;
  151.         }
  152.         
  153.     return pool;
  154.     }
  155.  
  156.  
  157. #ifdef DOCUMENTATION
  158.  
  159.     free_pool_memory() this will free and *release* all memory occupied by the
  160.     pool but not free the pool, letting you allocate some more.
  161.     
  162. #endif
  163.  
  164. free_pool_memory ( id )
  165. int        id;
  166. {
  167. _mem_pool_ptr    pool;
  168. _mem_blk_ptr    blk, nextblk;
  169.  
  170.     pool = find_pool(id);
  171.     if (pool == NULL)
  172.         return -1;
  173.     
  174.     for ( blk = pool->blk_list ; blk != (_mem_blk_ptr)0 ; ) {
  175.         nextblk = blk->next;
  176.         DPRINTF(3, ("pool_find_free_blk() Freeing Block x%lx from pool #%d!\n",
  177.                         blk, blk->pool->id));
  178. #ifdef _PM_STATS
  179.         pool->total_memory -= sizeof(_mem_blk) + blk->size;
  180.         pool->total_storage -= blk->size;
  181. #endif
  182.         mDISPOSPTR((Ptr)blk->memory);
  183.         mDISPOSPTR((Ptr)blk);
  184.  
  185.         blk = nextblk;
  186.         }
  187.  
  188.     pool->blk_list = NULL;
  189.     
  190.     return 0;
  191.     }
  192.  
  193.  
  194. #ifdef DOCUMENTATION
  195.  
  196.     free_pool() will free the pool's memory *and* free the pool (removing
  197.     it from the pool list) releasing all memory back to the heap.
  198.     
  199. #endif
  200.  
  201. free_pool ( id )
  202. int        id;
  203. {
  204. _mem_pool_ptr    pool;
  205.  
  206.     if (free_pool_memory(id) == -1)
  207.         return -1;
  208.     
  209.     pool = find_pool(id);
  210.     if (pool == NULL)
  211.         return -1;
  212.     
  213.     mDISPOSPTR((Ptr)pool);
  214.     
  215.     return 0;
  216.     }
  217.  
  218.  
  219. #ifdef DOCUMENTATION
  220.  
  221.     _pool_malloc() does the low level malloc() work in a specified pool.
  222.     
  223. #endif
  224.  
  225. char    *
  226. _pool_malloc(pool, size)
  227. _mem_pool_ptr    pool;
  228. u_long            size;
  229. {
  230. _mem_blk_ptr        blk;
  231. _mem_ptr_hdr_ptr    hdr = (_mem_ptr_hdr_ptr)0, freehdr;
  232. u_long                freesize, size_req;
  233. char                *ptr = (char *)0;
  234.  
  235.     DPRINTF(5, ("_pool_malloc() request of %ld bytes in pool #%d [x%lx]\n",
  236.                 size, pool->id, pool));
  237.  
  238.     size_req = (size < _PM_MIN_ALLOC_SIZE) ? _PM_MIN_ALLOC_SIZE : size;
  239.     size_req = INT_ALIGN(size_req, ALIGNMENT);
  240.  
  241. #ifdef _PM_STATS
  242.     pool->ave_req_size = ( ( (pool->ave_req_size * (float)pool->ave_req_total) + (float)size_req )
  243.                             / (float)(pool->ave_req_total + 1) );
  244.     pool->ave_req_total++;
  245. #endif
  246.  
  247.     blk = pool->blk_list;
  248.     if (blk == NULL) {
  249.         /* No blocks in pool, allocate one... */
  250.         blk = _pool_new_blk(pool, size_req);
  251.         }
  252.     else {
  253.         blk = _pool_find_free_blk(pool, size_req, &hdr);
  254.  
  255.         if (blk == (_mem_blk_ptr)0 || hdr == (_mem_ptr_hdr_ptr)0) {
  256.             /* No blocks that can support this size... */
  257.             blk = _pool_new_blk(pool, size_req);
  258.             }
  259.         else
  260.             DPRINTF(5, ("_pool_malloc() found free: blk x%lx hdr x%lx\n",
  261.                         blk, hdr));
  262.         }
  263.     
  264.     if (blk != (_mem_blk_ptr)0) {
  265.         /* Determine the pointer's location, establish, return. */
  266.         if (hdr == (_mem_ptr_hdr_ptr)0) {
  267.             hdr = (_mem_ptr_hdr_ptr) blk->memory;
  268.             DPRINTF(5, ("_pool_malloc() header of new blk blk->memory x%lx\n", blk->memory));
  269.             }
  270.         
  271.         DPRINTF(5, ("_pool_malloc() free hdr x%lx size %ld\n", hdr, GET_PTR_SIZE(hdr)));
  272.         if (hdr != (_mem_ptr_hdr_ptr)0) {
  273.             ptr = (char *)hdr + sizeof(_mem_ptr_hdr);
  274.             
  275.             if (size_req < GET_PTR_SIZE(hdr)) {
  276.                 /* Split this free block... */
  277.                 DPRINTF(5, ("_pool_malloc() split hdr x%lx into %ld used and %ld free\n",
  278.                             hdr, size_req, GET_PTR_SIZE(hdr) - (size_req + sizeof(_mem_ptr_hdr))));
  279.  
  280.                 freehdr = (_mem_ptr_hdr_ptr)
  281.                             ( (char *)hdr + sizeof(_mem_ptr_hdr) + size_req );
  282.                 freesize = GET_PTR_SIZE(hdr) - (sizeof(_mem_ptr_hdr) + size_req);
  283.                 bzero(freehdr, sizeof(_mem_ptr_hdr));
  284.                 SET_PTR_FREE(freehdr);
  285.                 SET_PTR_SIZE(freehdr, freesize);
  286.                 blk->max_free -= sizeof(_mem_ptr_hdr);
  287.                 }
  288.  
  289. #ifdef _PM_STATS    
  290.             pool->total_malloc += size_req;
  291. #endif
  292.  
  293.             blk->max_free -= size_req;
  294.             SET_PTR_USED(hdr);
  295.             SET_PTR_SIZE(hdr, size_req);
  296.             bzero(ptr, size_req);        /* Programmer's expect malloc() to zero. */
  297.             }
  298.         else {
  299.             /* ERROR: This should not happen!!! */
  300.             DPRINTF(1, ("ERROR: pool_malloc() could not get block's free hdr ptr\n"));
  301.             DACTION(2, { list_pool_forest(NULL); });
  302.             }
  303.         }
  304.     else {
  305.         /* ERROR, no block, no memory. */
  306.         DPRINTF(1, ("ERROR: pool_malloc() could not get a block\n"));
  307.         DACTION(2, { list_pool_forest(NULL); });
  308.         }
  309.     
  310.     DPRINTF(5, ("_pool_malloc() returning ptr x%lx\n", ptr));
  311.     return ptr;
  312.     }
  313.  
  314. #ifdef DOCUMENTATION
  315.  
  316.     _pool_free() does the low level work of a free().
  317.     
  318. #endif
  319.  
  320. _pool_free ( ptr )
  321. char    *ptr;
  322. {
  323. _mem_pool_ptr        pool;
  324. _mem_blk_ptr        blk;
  325. _mem_ptr_hdr_ptr    hdr, adjhdr, limit;
  326. int                    result = 0;
  327. u_long                ptr_size, new_size;
  328.  
  329.     if (ptr == (char *)0) {
  330.         /* WHOAH! NULL Pointers... */
  331.         DPRINTF(1, ("_pool_free() ptr NULL!"));
  332.         return -1;
  333.         }
  334.     
  335.     if ( ( (u_long)ptr & 1 ) != 0 ) {
  336.         /* WHOAH! ODD Pointers... */
  337.         DPRINTF(1, ("_pool_free() ptr ODD!"));
  338.         return -1;
  339.         }
  340.     
  341.     DPRINTF(5, ("_pool_free() free ptr x%lx\n", ptr));
  342.  
  343.     blk = _pool_find_ptr_blk(ptr);
  344.     
  345.     if (blk == (_mem_blk_ptr)0) {
  346.         /* We could not find this thing's blk! BUG!!! */
  347.         DPRINTF(1, ("ERROR: free(x%lx) could not find ptr's blk\n", ptr));
  348.         DACTION(2, { list_pool_forest(NULL); });
  349.         result = -1;
  350.         }
  351.     else {
  352.         /*
  353.         ** Now, if it is adjacent to free memory, combine.
  354.         ** NOTE: We only do this because it is SO DAMN CHEAP!!!!!
  355.         */
  356.  
  357.         /* Delay these assigns til we know ptr is good. (now) */
  358.         hdr = (_mem_ptr_hdr_ptr) ( (u_long)ptr - sizeof(_mem_ptr_hdr) );
  359.         ptr_size = GET_PTR_SIZE(hdr);
  360.  
  361.         DPRINTF(5, ("_pool_free() free hdr x%lx size %ld flags x%02x in blk x%lx\n",
  362.                     hdr, ptr_size, GET_PTR_FLAGS(hdr), blk));
  363.     
  364.         pool = blk->pool;
  365.         SET_PTR_FREE(hdr);
  366.         blk->max_free += ptr_size;
  367.         
  368.         adjhdr = (_mem_ptr_hdr_ptr)
  369.                     ( (char *)hdr + GET_PTR_SIZE(hdr) +
  370.                       sizeof(_mem_ptr_hdr) );
  371.         limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  372.         
  373.         if (adjhdr < limit && IS_PTR_FREE(adjhdr)) {
  374.             DPRINTF(5, ("_pool_free() merging hdr x%lx with freehdr x%lx\n", hdr, adjhdr));
  375.             
  376.             new_size =    GET_PTR_SIZE(hdr) +
  377.                         GET_PTR_SIZE(adjhdr) +
  378.                         sizeof(_mem_ptr_hdr);
  379.  
  380.             DPRINTF(5, ("_pool_free() merged hdr new_size %ld\n", new_size));
  381.             SET_PTR_SIZE(hdr, new_size);
  382.             blk->max_free += sizeof(_mem_ptr_hdr);
  383.             }    /* is adjacent free ? */
  384.         
  385. #ifdef _PM_STATS    
  386.         pool->total_malloc -= ptr_size;
  387. #endif
  388.  
  389. #ifdef _PM_DYNAMIC_FREE
  390.         if (block_is_freed(blk)) {
  391.             /* This blk is free-ed ... */
  392.             _mem_blk_ptr    tmpblk;
  393.  
  394.             if (blk == blk->pool->blk_list) {
  395.                 blk->pool->blk_list = blk->next;
  396.                 }
  397.             else {
  398.                 tmpblk = blk->pool->blk_list;
  399.                 while (tmpblk != (_mem_blk_ptr)0) {
  400.                     if (tmpblk->next == blk) {
  401.                         tmpblk->next = blk->next;
  402.                         break;
  403.                         }
  404.                     else
  405.                         tmpblk = tmpblk->next;
  406.                     }
  407.                 if (tmpblk == (_mem_blk_ptr)0)
  408.                     DPRINTF(1, ("ERROR: could not free blk x%lx from list!\n", blk));
  409.                 }
  410.             
  411.             DPRINTF(3, ("_pool_free() Freeing Block x%lx from pool #%d!\n",
  412.                         blk, blk->pool->id));
  413. #ifdef _PM_STATS
  414.             pool->total_memory -= sizeof(_mem_blk) + blk->size;
  415.             pool->total_storage -= blk->size;
  416. #endif
  417.             mDISPOSPTR((Ptr)blk->memory);
  418.             mDISPOSPTR((Ptr)blk);
  419.             }    /* if (block_is_freed(blk)) */
  420. #endif _PM_DYNAMIC_FREE
  421.  
  422.         result = 0;
  423.         }    /* else we found the block containing the ptr. */
  424.     
  425.     return result;
  426.     }
  427.  
  428. #ifdef DOCUMENTATION
  429.  
  430.     block_is_freed() determines if all memory in a given block is free.
  431.     
  432. #endif
  433.  
  434. block_is_freed(blk)
  435. _mem_blk_ptr    blk;
  436. {
  437. int            freed = 1;
  438. _mem_ptr_hdr_ptr    loophdr, limit;
  439.  
  440. /*
  441. ** This loop is not as expensive as you might think, since most of the
  442. ** time we've "merged" into few "ptrs", and in allocated cases we will
  443. ** break out of the loop almost immediately.
  444. */
  445.  
  446.     if (blk != NULL) {
  447.         loophdr = (_mem_ptr_hdr_ptr) blk->memory;
  448.         limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  449.         while (loophdr < limit) {
  450.             if (! IS_PTR_FREE(loophdr)) {
  451.                 freed = 0;
  452.                 break;
  453.                 }
  454.             
  455.             loophdr = (_mem_ptr_hdr_ptr)
  456.                         ((char *)loophdr + GET_PTR_SIZE(loophdr) + sizeof(_mem_ptr_hdr));
  457.             }
  458.         }
  459.     else
  460.         freed = 0;    /* ? Or is it really free? */
  461.     
  462.     return freed;
  463.     }
  464.  
  465.  
  466. #ifdef DOCUMENTATION
  467.  
  468.     _pool_new_blk() allocate a new memory block to a pool. This is called
  469.     by the low level malloc() code when new memory is needed.
  470.     
  471. #endif
  472.  
  473. _mem_blk_ptr
  474. _pool_new_blk(pool, size_req)
  475. _mem_pool_ptr    pool;
  476. u_long            size_req;    /* size required */
  477. {
  478. u_long                blk_size;
  479. _mem_blk_ptr        new_blk;
  480. _mem_ptr_hdr_ptr    hdr;
  481.  
  482.     DPRINTF(5, ("_pool_new_blk() req_size %ld pool #%d [x%lx]\n", size_req, pool->id, pool));
  483.  
  484.     if ((size_req + sizeof(_mem_ptr_hdr)) > pool->pref_blk_size) {
  485.         blk_size = ((size_req / pool->pref_blk_size) + 1) * pool->pref_blk_size;
  486. #ifdef _PM_STATS
  487.         if (blk_size > pool->max_blk_size)
  488.             pool->max_blk_size = blk_size;
  489. #endif
  490.         }
  491.     else
  492.         blk_size = pool->pref_blk_size;
  493.     
  494.     blk_size = INT_ALIGN(blk_size, ALIGNMENT);
  495.     
  496. #ifdef _PM_STATS
  497.     pool->ave_blk_size = ( ( (pool->ave_blk_size * (float)pool->ave_blk_total) + (float)blk_size )
  498.                             / (float)(pool->ave_blk_total + 1) );
  499.     pool->ave_blk_total++;
  500. #endif
  501.  
  502.     new_blk = (_mem_blk_ptr) mNEWPTR(sizeof(_mem_blk));
  503.     if (new_blk == (_mem_blk_ptr)0)
  504.         return new_blk;
  505.     
  506.     /*
  507.     ** NOTE: We assume here that mNEWPTR() gives us proper alignment.
  508.     */
  509.     new_blk->memory = (char *) mNEWPTR(blk_size);
  510. #ifdef NEVER_DEFINED
  511.     if (new_blk->memory == (char *)0) {
  512.         /* Attempt to handle the request only. */
  513.         blk_size = size_req + sizeof(_mem_ptr_hdr);
  514.         blk_size = INT_ALIGN(blk_size, ALIGNMENT);
  515.         new_blk->memory = (char *) mNEWPTR(blk_size);
  516.         }
  517. #endif
  518.     
  519.     if (new_blk->memory == (char *)0) {
  520.         mDISPOSPTR((Ptr)new_blk);
  521.         DPRINTF(10, ("_pool_new_blk(pool:x%lx, size:%ld) Out of memory.\n", pool, size_req));
  522.         return (_mem_blk_ptr)0;
  523.         }
  524.     
  525. #ifdef _PM_STATS
  526.     pool->total_memory += sizeof(_mem_blk) + blk_size;
  527.     pool->total_storage += blk_size;
  528. #endif
  529.  
  530.     new_blk->pool = pool;
  531.     new_blk->size = blk_size;
  532.     new_blk->max_free = blk_size - sizeof(_mem_ptr_hdr);
  533.     
  534.     /* Add to the block list. */
  535.     new_blk->next = pool->blk_list;
  536.     pool->blk_list = new_blk;
  537.     
  538.     hdr = (_mem_ptr_hdr_ptr) new_blk->memory;
  539.     bzero(hdr, sizeof(_mem_ptr_hdr));
  540.     
  541.     SET_PTR_FREE(hdr);
  542.     SET_PTR_SIZE(hdr, ( blk_size - sizeof(_mem_ptr_hdr) ) );
  543.     
  544.     DPRINTF(5, ("_pool_new_blk() new blk x%lx size %ld memory x%lx pool #%d [x%lx]\n",
  545.             new_blk, new_blk->size, new_blk->memory, pool->id, pool));
  546.     return new_blk;
  547.     }
  548.     
  549.  
  550. #ifdef DOCUMENTATION
  551.  
  552.     _pool_find_free_blk() looks for a block in the pool with enough free memory
  553.     to allocate the "size_req" bytes.
  554.     
  555. #endif
  556.  
  557. _mem_blk_ptr
  558. _pool_find_free_blk(pool, size_req, hdr_ptr)
  559. _mem_pool_ptr        pool;
  560. u_long                size_req;    /* size required */
  561. _mem_ptr_hdr_ptr    *hdr_ptr;
  562. {
  563. _mem_blk_ptr        blk, use_this_blk;
  564. _mem_ptr_hdr_ptr    loophdr, limit;
  565. long                hdrsize, max_size;
  566.  
  567. #ifdef _PM_DYNAMIC_MERGING
  568. _mem_ptr_hdr_ptr    lasthdr, nexthdr, blkhdr;
  569. long                lastsize, nextsize;
  570. #endif _PM_DYNAMIC_MERGING
  571.  
  572.     blk = pool->blk_list;
  573.     max_size = 0x3FFFFFFF;
  574.     for (use_this_blk=NULL; blk != (_mem_blk_ptr)0 ; blk=blk->next) {
  575.         if (blk->max_free >= size_req) {
  576.             if (use_this_blk == NULL) {
  577.                 use_this_blk = blk;
  578.                 max_size = blk->size;
  579.                 }
  580.             else if (blk->size < max_size) {
  581.                 use_this_blk = blk;
  582.                 max_size = blk->size;
  583.                 }
  584.             }
  585.         }
  586.     
  587.     blk = use_this_blk;
  588.     if (blk != NULL) {
  589.         loophdr = (_mem_ptr_hdr_ptr) blk->memory;
  590.         limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  591. #ifdef _PM_DYNAMIC_MERGING
  592.         lasthdr = (_mem_ptr_hdr_ptr)0;
  593. #endif _PM_DYNAMIC_MERGING
  594.         while (loophdr < limit) {
  595.             if (IS_PTR_FREE(loophdr)) {
  596.                 hdrsize = GET_PTR_SIZE(loophdr);
  597.                 if (hdrsize >= size_req) {
  598.                     DPRINTF(5, ("pool_find_free_blk() Found blk x%lx hdr x%lx pool #%d [x%lx]\n",
  599.                                 blk, loophdr, pool->id, pool));
  600.                     
  601.                     *hdr_ptr = loophdr;
  602.                     return blk;
  603.                     }
  604.  
  605. #ifdef _PM_DYNAMIC_MERGING
  606.                 else {
  607.                     nexthdr = (_mem_ptr_hdr_ptr)
  608.                                 ( (char *)loophdr + hdrsize + sizeof(_mem_ptr_hdr) );
  609.                     if (nexthdr < limit) {
  610.                         if (IS_PTR_FREE(nexthdr)) {
  611.                             nextsize = GET_PTR_SIZE(nexthdr);
  612.                             blk->max_free += sizeof(_mem_ptr_hdr);    /* We're gonna merge... */
  613.                             if ((nextsize + hdrsize + sizeof(_mem_ptr_hdr)) >= size_req) {
  614.                                 DPRINTF(3, ("pool_find_free_blk() F-Merge blk x%lx hdr1 x%lx hdr2 x%lx \n",
  615.                                             blk, loophdr, nexthdr));
  616.                                 
  617.                                 hdrsize = nextsize + hdrsize + sizeof(_mem_ptr_hdr);
  618.                                 SET_PTR_SIZE(loophdr, hdrsize);
  619.                                 *hdr_ptr = loophdr;
  620.                                 return blk;
  621.                                 }
  622.                             else {
  623.                                 /* OK, so merge anyways... */
  624.                                 hdrsize = nextsize + hdrsize + sizeof(_mem_ptr_hdr);
  625.                                 SET_PTR_SIZE(loophdr, hdrsize);
  626.                                 }
  627.                             }
  628.                         }
  629.                     if (lasthdr != (_mem_ptr_hdr_ptr)0) {
  630.                         if (IS_PTR_FREE(lasthdr)) {
  631.                             lastsize = GET_PTR_SIZE(lasthdr);
  632.                             blk->max_free += sizeof(_mem_ptr_hdr);    /* We're gonna merge... */
  633.                             if ((lastsize + hdrsize + sizeof(_mem_ptr_hdr)) >= size_req) {
  634.                                 DPRINTF(3, ("pool_find_free_blk() R-Merge blk x%lx hdr1 x%lx hdr2 x%lx \n",
  635.                                             blk, lasthdr, loophdr));
  636.                                 
  637.                                 hdrsize = lastsize + hdrsize + sizeof(_mem_ptr_hdr);
  638.                                 SET_PTR_SIZE(lasthdr, hdrsize);
  639.                                 *hdr_ptr = lasthdr;
  640.                                 return blk;
  641.                                 }
  642.                             else {
  643.                                 /* OK, so merge anyways... */
  644.                                 hdrsize = lastsize + hdrsize + sizeof(_mem_ptr_hdr);
  645.                                 SET_PTR_SIZE(lasthdr, hdrsize);
  646.                                 }
  647.                             loophdr = lasthdr;
  648.                             lasthdr = (_mem_ptr_hdr_ptr)0;
  649.                             }
  650.                         }
  651. #ifdef _PM_DYNAMIC_FREE
  652.                     blkhdr = (_mem_ptr_hdr_ptr)blk->memory;
  653.                     if (IS_PTR_FREE(blkhdr)) {
  654.                         if ((GET_PTR_SIZE(blkhdr) + sizeof(_mem_ptr_hdr)) == blk->size) {
  655.                             /* This blk is free-ed ... */
  656.                             
  657.                             _mem_blk_ptr    tmpblk, next;
  658.             
  659.                             if (blk == blk->pool->blk_list) {
  660.                                 blk->pool->blk_list = next = blk->next;
  661.                                 }
  662.                             else {
  663.                                 tmpblk = blk->pool->blk_list;
  664.                                 while (tmpblk != (_mem_blk_ptr)0) {
  665.                                     if (tmpblk->next == blk) {
  666.                                         tmpblk->next = next = blk->next;
  667.                                         break;
  668.                                         }
  669.                                     else
  670.                                         tmpblk = tmpblk->next;
  671.                                     }
  672.                                 if (tmpblk == (_mem_blk_ptr)0)
  673.                                     DPRINTF(1, ("pool_find_free_blk() ERROR: could not free blk x%lx from list!\n", blk));
  674.                                 }
  675.                             
  676.                             DPRINTF(3, ("pool_find_free_blk() Freeing Block x%lx from pool #%d!\n",
  677.                                         blk, blk->pool->id));
  678. #ifdef _PM_STATS
  679.                             pool->total_memory -= sizeof(_mem_blk) + blk->size;
  680.                             pool->total_storage -= blk->size;
  681. #endif
  682.                             mDISPOSPTR((Ptr)blk->memory);
  683.                             mDISPOSPTR((Ptr)blk);
  684.                             blk = next;
  685.                             break;    /* The while (hdr) loop, into while (blk) loop */
  686.                             }
  687.                         }    /* if (IS_PTR_FREE(blkhdr)) */
  688. #endif _PM_DYNAMIC_FREE
  689.  
  690.                     }
  691. #endif _PM_DYNAMIC_MERGING
  692.  
  693.                 }
  694. #ifdef _PM_DYNAMIC_MERGING
  695.             lasthdr = loophdr;
  696. #endif _PM_DYNAMIC_MERGING
  697.             loophdr = (_mem_ptr_hdr_ptr)
  698.                         ((char *)loophdr + GET_PTR_SIZE(loophdr) + sizeof(_mem_ptr_hdr));
  699.             }
  700.         }
  701.     
  702.     *hdr_ptr = (_mem_ptr_hdr_ptr)0;
  703.     return blk;
  704.     }
  705.     
  706.  
  707. #ifdef DOCUMENTATION
  708.  
  709.     _pool_find_ptr_blk() finds the block containing this pointer in "ptr".
  710.     
  711. #endif
  712.  
  713. _mem_blk_ptr
  714. _pool_find_ptr_blk(ptr)
  715. char    *ptr;
  716. {
  717. _mem_pool_ptr    pool;
  718. _mem_blk_ptr    blk;
  719.  
  720.     /*
  721.     ** Since the default list is stored at the front of the forest list,
  722.     ** we inherently search the default forest first. Nice.
  723.     */
  724.     pool = _mem_pool_forest;
  725.     
  726.     while (pool != (_mem_pool_ptr)0) {
  727.         blk = pool->blk_list;
  728.         
  729.         while (blk != (_mem_blk_ptr)0) {
  730.             if ( ( ptr >= blk->memory ) &&
  731.                  ( ptr <= ((char *)blk->memory + blk->size) ) )
  732.                 return blk;
  733.             else
  734.                 blk = blk->next;
  735.             }
  736.         
  737.         pool = pool->next;
  738.         }
  739.     
  740.     return (_mem_blk_ptr)0;
  741.     }
  742.  
  743.  
  744. #ifdef DOCUMENTATION
  745.  
  746.     merge_free_list() runs the routine to merge and "release" any free-ed
  747.     blocks back into the heap.
  748.     
  749. #endif
  750.  
  751. merge_free_list()
  752. {
  753.     return _pool_free_list_merge(_default_mem_pool);
  754.     }
  755.  
  756.  
  757. #ifdef DOCUMENTATION
  758.  
  759.     _pool_free_list_merge() will merge and "release" any free-ed blocks
  760.     back into the heap.
  761.     
  762. #endif
  763.  
  764. _pool_free_list_merge(pool)
  765. _mem_pool_ptr        pool;
  766. {
  767. _mem_blk_ptr        blk, nextblk;
  768. _mem_ptr_hdr_ptr    loophdr, limit, nexthdr, blkhdr;
  769. int                    result = 0;
  770. long                hdrsize, nextsize;
  771.  
  772.     blk = pool->blk_list;
  773.     while (blk != (_mem_blk_ptr)0) {
  774.         loophdr = blkhdr = (_mem_ptr_hdr_ptr)blk->memory;
  775.         limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  776.         while (loophdr < limit) {
  777.             if (IS_PTR_FREE(loophdr)) {
  778.                 hdrsize = GET_PTR_SIZE(loophdr);
  779.                 nexthdr = (_mem_ptr_hdr_ptr)
  780.                             ( (char *)loophdr + hdrsize + sizeof(_mem_ptr_hdr) );
  781.                 /* Now loop and merge free ptr's til used one is hit... */
  782.                 while (nexthdr < limit) {
  783.                     if (IS_PTR_FREE(nexthdr)) {
  784.                         nextsize = GET_PTR_SIZE(nexthdr);
  785.                         blk->max_free += sizeof(_mem_ptr_hdr);    /* We're gonna merge... */
  786.                         hdrsize = nextsize + hdrsize + sizeof(_mem_ptr_hdr);
  787.                         SET_PTR_SIZE(loophdr, hdrsize);
  788.                         nexthdr = (_mem_ptr_hdr_ptr)
  789.                                     ( (char *)loophdr + hdrsize + sizeof(_mem_ptr_hdr) );
  790.                         }
  791.                     else
  792.                         break;
  793.                     }
  794.                 }
  795.             
  796.             loophdr = (_mem_ptr_hdr_ptr)
  797.                         ((char *)loophdr + GET_PTR_SIZE(loophdr) + sizeof(_mem_ptr_hdr));
  798.             }
  799.  
  800.         /* Get next block now, so _PM_DYNAMIC_FREE can modify blk as desired */
  801.         nextblk = blk->next;
  802.  
  803. #ifdef _PM_DYNAMIC_FREE
  804.         if (IS_PTR_FREE(blkhdr)) {
  805.             if ((GET_PTR_SIZE(blkhdr) + sizeof(_mem_ptr_hdr)) == blk->size) {
  806.                 /* This blk is free-ed ... */
  807.                 _mem_blk_ptr    tmpblk;
  808.  
  809.                 if (blk == blk->pool->blk_list) {
  810.                     blk->pool->blk_list = blk->next;
  811.                     }
  812.                 else {
  813.                     tmpblk = blk->pool->blk_list;
  814.                     while (tmpblk != (_mem_blk_ptr)0) {
  815.                         if (tmpblk->next == blk) {
  816.                             tmpblk->next = blk->next;
  817.                             break;
  818.                             }
  819.                         else
  820.                             tmpblk = tmpblk->next;
  821.                         }
  822.                     if (tmpblk == (_mem_blk_ptr)0)
  823.                         DPRINTF(1, ("pool_find_free_blk() ERROR: could not free blk x%lx from list!\n", blk));
  824.                     }
  825.                 
  826.                 DPRINTF(3, ("pool_find_free_blk() Freeing Block x%lx from pool #%d!\n",
  827.                             blk, blk->pool->id));
  828. #ifdef _PM_STATS
  829.                 pool->total_memory -= sizeof(_mem_blk) + blk->size;
  830.                 pool->total_storage -= blk->size;
  831. #endif
  832.                 result += blk->size + sizeof(_mem_blk);
  833.                 mDISPOSPTR((Ptr)blk->memory);
  834.                 mDISPOSPTR((Ptr)blk);
  835.                 }
  836.             
  837.             }    /* if (IS_PTR_FREE(blkhdr)) */
  838. #endif _PM_DYNAMIC_FREE
  839.         
  840.         blk = nextblk;
  841.         }
  842.     
  843.     return result;
  844.     }
  845.     
  846.  
  847. #ifdef DOCUMENTATION
  848.  
  849.     get_malloc_stats() return several statistics about the default heap.
  850.     
  851. #endif
  852.  
  853. get_malloc_stats(total_memory, total_free, total_malloc)
  854. long        *total_memory;
  855. long        *total_free;
  856. long        *total_malloc;
  857. {
  858. _mem_pool_ptr        pool;
  859. _mem_blk_ptr        blk;
  860. _mem_ptr_hdr_ptr    hdr, limit;
  861. u_long                total_size, used_space, free_space;
  862. u_long                ptr_size;
  863.  
  864.     pool = _default_mem_pool;
  865.     blk = pool->blk_list;
  866.     total_size = used_space = free_space = 0;
  867.     for ( ; blk != (_mem_blk_ptr)0; ) {
  868.         hdr = (_mem_ptr_hdr_ptr) blk->memory;
  869.         limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  870.         total_size += blk->size;
  871.         for ( ; hdr && hdr < limit; ) {
  872.             ptr_size = GET_PTR_SIZE(hdr);
  873.             if (IS_PTR_FREE(hdr))
  874.                 free_space += ptr_size;
  875.             else
  876.                 used_space += ptr_size;
  877.             
  878.             hdr = (_mem_ptr_hdr_ptr)
  879.                     ( (char *)hdr + GET_PTR_SIZE(hdr) + sizeof(_mem_ptr_hdr) );
  880.             }
  881.         
  882.         blk = blk->next;
  883.         }
  884.     
  885.     *total_memory = total_size;
  886.     *total_free = free_space;
  887.     *total_malloc = used_space;
  888.     }
  889.  
  890. #ifdef DEBUG
  891.  
  892. #include <stdio.h>
  893.  
  894. char    temp_str[512];
  895.  
  896. list_all_pool_stats(file)
  897. FILE    *file;
  898. {
  899. _mem_pool_ptr        pool;
  900.  
  901.     pool = _mem_pool_forest;
  902.     
  903.     while (pool != (_mem_pool_ptr)0) {
  904.         
  905.         list_pool_stats(file, pool);
  906.  
  907.         pool = pool->next;
  908.         }
  909.     
  910.     }
  911.  
  912.  
  913. list_pool_stats(file, pool)
  914. FILE    *file;
  915. _mem_pool_ptr        pool;
  916. {
  917. _mem_blk_ptr        blk;
  918. _mem_ptr_hdr_ptr    hdr, limit;
  919. int                    i, j;
  920. int                    num_used_hdrs, num_free_hdrs;
  921. u_long                used_hdr_space, free_hdr_space;
  922. u_long                ptr_size, max_free_size, max_used_size;
  923. float                ave_used_size, ave_free_size, frag_ratio;
  924.  
  925.     if (file == (FILE *)0) {
  926.         file = stdout;
  927.         }
  928.     
  929.     fprintf(file, "POOL STATISTICS FOR ID#%d @ x%lx blk_list x%lx pref_blk_size %ld\n",
  930.             pool->id, pool, pool->blk_list, pool->pref_blk_size);
  931.  
  932. #ifdef _PM_STATS
  933.     fprintf(file, "\tMEMORY: Total memory %ld Total ptr space %ld Currently malloc-ed %ld\n",
  934.             pool->total_memory, pool->total_storage, pool->total_malloc);
  935.     fprintf(file, "\tREQUESTS: Ave req size %f Total reqs %ld Total size reqs %f\n",
  936.             pool->ave_req_size, pool->ave_req_total, 
  937.             (float) (pool->ave_req_size * (float)pool->ave_req_total));
  938.     fprintf(file, "\tBLOCKS: Max block size %ld Ave block size %f\n",
  939.             pool->max_blk_size, pool->ave_blk_size);
  940.     fprintf(file, "\tBLOCKS: Total ave blocks %ld Total ave size %f\n",
  941.             pool->ave_blk_total,(float) (pool->ave_blk_size * (float)pool->ave_blk_total));
  942. #endif
  943.  
  944.         fprintf(file, "POOL BLOCK STATISTICS:\n");
  945.         
  946.         blk = pool->blk_list;
  947.         for (i=0; blk != (_mem_blk_ptr)0; i++) {
  948.             hdr = (_mem_ptr_hdr_ptr) blk->memory;
  949.             limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  950.             num_used_hdrs = num_free_hdrs = 0;
  951.             used_hdr_space = free_hdr_space = 0;
  952.             max_free_size = max_used_size = 0;
  953.             for (j=0; hdr && hdr < limit; j++) {
  954.                 ptr_size = GET_PTR_SIZE(hdr);
  955.                 if (IS_PTR_FREE(hdr)) {
  956.                     num_free_hdrs++;
  957.                     free_hdr_space += ptr_size;
  958.                     if (ptr_size > max_free_size)
  959.                         max_free_size = ptr_size;
  960.                     }
  961.                 else {
  962.                     num_used_hdrs++;
  963.                     used_hdr_space += ptr_size;
  964.                     if (ptr_size > max_used_size)
  965.                         max_used_size = ptr_size;
  966.                     }
  967.                 
  968.                 hdr = (_mem_ptr_hdr_ptr)
  969.                         ( (char *)hdr + GET_PTR_SIZE(hdr) + sizeof(_mem_ptr_hdr) );
  970.                 }
  971.             
  972.             if (num_free_hdrs == 0)
  973.                 ave_free_size = (float)0.0;
  974.             else
  975.                 ave_free_size = (float)free_hdr_space / (float)num_free_hdrs;
  976.             
  977.             if (num_used_hdrs == 0)
  978.                 ave_used_size = (float)0.0;
  979.             else
  980.                 ave_used_size = (float)used_hdr_space / (float)num_used_hdrs;
  981.             
  982.             if (num_used_hdrs == 0) {
  983.                 frag_ratio = (float)num_free_hdrs / 2.0;
  984.                 }
  985.             else {
  986.                 frag_ratio = (float)num_free_hdrs / (float)num_used_hdrs;
  987.                 }
  988.             
  989.             fprintf(file, "\tBLOCK #%-4d Fragmentation Ratio %5.2f\n", i, frag_ratio);
  990.             fprintf(file, "\t      #%-4d    Block Size %ld Ptr x%lx MaxFree %ld\n",
  991.                     i, blk->size, blk->memory, blk->max_free);
  992.             fprintf(file, "\t      #%-4d    Number free ptrs %d Number used ptrs %d\n",
  993.                     i, num_free_hdrs, num_used_hdrs);
  994.             fprintf(file, "\t      #%-4d    Free space %ld Used space %ld\n",
  995.                     i, free_hdr_space, used_hdr_space);
  996.             fprintf(file, "\t      #%-4d    Max free ptr %ld Max used ptr %ld\n",
  997.                     i, max_free_size, max_used_size);
  998.             fprintf(file, "\t      #%-4d    Ave free ptr size %5.1f Ave used ptr size %5.1f\n",
  999.                     i, ave_free_size, ave_used_size);
  1000.  
  1001.             blk = blk->next;
  1002.             }
  1003.     }
  1004.  
  1005.  
  1006. list_pool_forest(file, with_data)
  1007. FILE    *file;
  1008. int        with_data;
  1009. {
  1010. _mem_pool_ptr        pool;
  1011. _mem_blk_ptr        blk;
  1012. _mem_ptr_hdr_ptr    hdr, limit;
  1013. int                    i, j;
  1014. extern char            temp_str[];
  1015.  
  1016.     if (file == (FILE *)0) {
  1017.         file = stdout;
  1018.         }
  1019.     
  1020.     pool = _mem_pool_forest;
  1021.     while (pool != (_mem_pool_ptr)0) {
  1022.         
  1023.         list_pool_stats(file, pool);
  1024.         
  1025.         blk = pool->blk_list;
  1026.         for (i=0; blk != (_mem_blk_ptr)0; i++) {
  1027.             fprintf(file, "   BLK #%05d ; @ x%lx ; blk_size %ld ; memory x%lx ; max_free %ld\n",
  1028.                     i, blk, blk->size, blk->memory, blk->max_free);
  1029.             fprintf(file, "   BLK          pool x%lx ; next blk x%lx\n", blk->pool, blk->next);
  1030.             
  1031.             hdr = (_mem_ptr_hdr_ptr) blk->memory;
  1032.             limit = (_mem_ptr_hdr_ptr) ((char *)blk->memory + blk->size);
  1033.             for (j=0; hdr && hdr < limit; j++) {
  1034.                 sprintf(temp_str, "      PTR #%d ; hdr x%lx ; nxt x%08lx ; size %ld ; flgs x%02x",
  1035.                         j, hdr, hdr->size, GET_PTR_SIZE(hdr), GET_PTR_FLAGS(hdr));
  1036.                 if (with_data)
  1037.                     hex_dump(file, temp_str,
  1038.                             (char *)((char *)hdr + sizeof(_mem_ptr_hdr)),
  1039.                             GET_PTR_SIZE(hdr));
  1040.                 else
  1041.                     fprintf(file, "%s\n", temp_str);
  1042.                 
  1043.                 hdr = (_mem_ptr_hdr_ptr)
  1044.                         ( (char *)hdr + GET_PTR_SIZE(hdr) + sizeof(_mem_ptr_hdr) );
  1045.                 }
  1046.             
  1047.             blk = blk->next;
  1048.             }
  1049.         
  1050.         pool = pool->next;
  1051.         }
  1052.     }
  1053.  
  1054. #define ROW_BYTES        16
  1055.  
  1056. hex_dump(output, title, ptr, bytes)
  1057. FILE    *output;
  1058. char    *title;
  1059. char    *ptr;
  1060. long    bytes;
  1061. {
  1062. int                rows, residue, i, j;
  1063. unsigned char    save_buf[ROW_BYTES+2];
  1064. unsigned char    hex_buf[4];
  1065. char            hex_chars[20];
  1066.     strcpy(hex_chars, "0123456789ABCDEF");
  1067.     
  1068.     fprintf(output, "\n%s - x%lX (%ld) bytes.\n", title, bytes, bytes);
  1069.     rows = bytes >> 4;
  1070.     residue = bytes & 0x0000000F;
  1071.     for (i=0; i<rows; i++) {
  1072.         fprintf(output, "%04.4X:", i * ROW_BYTES);
  1073.         for (j=0; j<ROW_BYTES; j++) {
  1074.             save_buf[j] = *ptr++;
  1075.             hex_buf[0] = hex_chars[(save_buf[j] >> 4) & 0x0F];
  1076.             hex_buf[1] = hex_chars[save_buf[j] & 0x0F];
  1077.             hex_buf[2] = '\0';
  1078.             fprintf(output, " %2.2s", hex_buf);
  1079.             if (save_buf[j] < 0x20 || save_buf[j] > 0xD9) save_buf[j] = '.';
  1080.             }
  1081.         save_buf[ROW_BYTES+1] = '\0';
  1082.         fprintf(output, "\t/* %16.16s */\n", save_buf);
  1083.         }
  1084.     if (residue) {
  1085.         fprintf(output, "%04.4X:", i * ROW_BYTES);
  1086.         for (j=0; j<residue; j++) {
  1087.             save_buf[j] = *ptr++;
  1088.             hex_buf[0] = hex_chars[(save_buf[j] >> 4) & 0x0F];
  1089.             hex_buf[1] = hex_chars[save_buf[j] & 0x0F];
  1090.             hex_buf[2] = '\0';
  1091.             fprintf(output, " %2.2s", hex_buf);
  1092.             if (save_buf[j] < 0x20 || save_buf[j] > 0xD9) save_buf[j] = '.';
  1093.             }
  1094.         for (/*j INHERITED*/; j<ROW_BYTES; j++) {
  1095.             save_buf[j] = ' ';
  1096.             fprintf(output, "   ");
  1097.             }
  1098.         save_buf[ROW_BYTES+1] = '\0';
  1099.         fprintf(output, "\t/* %16.16s */\n", save_buf);
  1100.         }
  1101.     }
  1102.  
  1103. #ifdef TESTING
  1104.  
  1105. main(argc, argv)
  1106. char    *argc;
  1107. char    *argv[];
  1108. {
  1109. int        i;
  1110. _mem_pool_ptr pool;
  1111. char    *ptr, *aptr[20];
  1112. char    input[128];
  1113. #pragma unused (argc, argv)
  1114.  
  1115.     printf("Debug level?\n");
  1116.     gets(input);
  1117.     if (input[0] == '\0' || input[0] == 'q')
  1118.         return 0;
  1119.     
  1120.     pool_malloc_debug_level = atoi(input);
  1121.     printf("Debug level set to %d\n", pool_malloc_debug_level);
  1122.     
  1123.     fprintf(stderr, "******************** START ********************\n");
  1124.     list_pool_forest(stderr, 0);
  1125.     
  1126.     printf("Allocating in default (system) pool...\n");
  1127.     for (i = 10 ; i < (10 * 1024) ; i += 128)
  1128.         if (malloc(i) == NULL)
  1129.             break;
  1130.     
  1131.     fprintf(stderr, "******************** ## 1 ## ********************\n");
  1132.     list_pool_forest(stderr, 0);
  1133.     
  1134.     printf("Allocating and Free-ing in default (system) pool...\n");
  1135.     for (i = 10 ; i < (10 * 1024) ; i += 128)
  1136.         if ((ptr = malloc(i)) != NULL)
  1137.             free(ptr);
  1138.         else
  1139.             break;
  1140.         
  1141.     fprintf(stderr, "******************** ## 2 ## ********************\n");
  1142.     list_pool_forest(stderr, 0);
  1143.     
  1144.     printf("Allocating and Free-ing again in default (system) pool...\n");
  1145.     for (i = 0 ; i < 20 ; i++)
  1146.         aptr[i] = NULL;
  1147.     for (i = 0 ; i < 20 ; i++) {
  1148.         aptr[i] = malloc(i * 128);
  1149.         if (aptr[i] == NULL)
  1150.             break;
  1151.         }
  1152.     for (i = 19 ; i >= 0 ; i--)
  1153.         if (aptr[i] != NULL) {
  1154.             free(aptr[i]);
  1155.             }
  1156.         
  1157.     fprintf(stderr, "******************** ## 3 ## ********************\n");
  1158.     list_pool_forest(stderr, 0);
  1159.     
  1160.     pool = new_malloc_pool ( 2001, (16 * 1024) );
  1161.     printf("new_malloc_pool ( 2001, %d ) returns x%lx\n", (16 * 1024), pool);
  1162.     if (pool) {
  1163.         set_default_pool ( 2001 );
  1164.         
  1165.         printf("Allocating in pool #2001...\n");
  1166.         for (i = 10 ; i < (10 * 1024) ; i += 128)
  1167.             if (malloc(i) == NULL)
  1168.                 break;
  1169.         }
  1170.  
  1171.     fprintf(stderr, "******************** ## 4 ## ********************\n");
  1172.     list_pool_forest(stderr, 0);
  1173.     
  1174.     printf("Free-ing memory in pool #2001...\n");
  1175.     free_pool_memory ( 2001 );
  1176.  
  1177.     fprintf(stderr, "******************** ## 5 ## ********************\n");
  1178.     list_pool_forest(stderr, 0);
  1179.     
  1180.     printf("Done.\n");
  1181.     }
  1182.  
  1183. #endif TESTING
  1184.  
  1185. #endif _PM_STATS
  1186.  
  1187. bzero(ptr, size)
  1188. register char *ptr;
  1189. register u_long size;
  1190. {
  1191.     while (size-- > 0) *ptr++ = '\0';
  1192.     }
  1193.  
  1194.